home *** CD-ROM | disk | FTP | other *** search
/ BCI NET / BCI NET Dec 94.iso / archives / utilities / print / pspager.lha / psp / ps_package.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-18  |  9.5 KB  |  409 lines

  1. /* ps_package.c */
  2.  
  3. #include "ps_package.h"
  4. #include "pspager.h"
  5. #include <string.h>
  6. #include <ctype.h>
  7. #ifdef AMIGA
  8. #include <utilities.h>
  9. #else
  10. #include "utilities.h"
  11. #endif
  12.  
  13.  
  14. /*--- private global data --------------------------------------------------------*/
  15.  
  16. #define INBUF_SIZE   256*KB
  17. #define SYMBUF_SIZE  1*KB
  18. #define SYMTAB_SIZE  13
  19. #define PAGE_LIMIT   71
  20. #define IFSTK_SIZE   8
  21.  
  22. #define CpyStr(s1,s2) { \
  23.   if(s1 < s2) { \
  24.     if(wrPtr+((s2)-(s1)) >= wrEnd) \
  25.       FatalExit("input buffer overflow"); \
  26.     strncpy(wrPtr,s1,s2-s1); \
  27.     wrPtr += s2-s1; \
  28.   } \
  29. }
  30.  
  31. #define CpyChar(ch) { \
  32.   if(wrPtr == wrEnd) \
  33.     FatalExit("input buffer overflow"); \
  34.   *wrPtr = (ch), wrPtr++; \
  35. }
  36.  
  37. static char *inBuf,*wrPtr,*rdPtr;
  38. static char *symBuf,*symPtr,*symEnd,**symTab;
  39.  
  40.  
  41. /*--- private functions ---------------------------------------------------------*/
  42.  
  43. static bool PSSymDefined(char *symName)
  44. {
  45.   char *cp;
  46.   int h = 0,d = 1;
  47.  
  48.   if(!symTab)
  49.     return FALSE;
  50.  
  51.   for(cp=symName; *cp!='\0'; cp++)
  52.     h = (256*h + *cp) % SYMTAB_SIZE;
  53.   FOREVER
  54.     if(symTab[h])
  55.       if(strcmp(symTab[h],symName) == 0)
  56.         return TRUE;
  57.       else {
  58.         h += d; d += 2; /* collision */
  59.         if(h >= SYMTAB_SIZE)
  60.           h -= SYMTAB_SIZE;
  61.         if(d == SYMTAB_SIZE)
  62.           FatalExit("symbol table overflow");
  63.       }
  64.     else
  65.       return FALSE; /* empty slot */
  66. }
  67.  
  68.  
  69. /*--- public functions ----------------------------------------------------------*/
  70.  
  71. /*  PSPrintHdr
  72. **  ----------
  73. **  prints a PostScript 3.0 header to stdout, parameters are: name of file, file
  74. **  modification date or current date, number of pages, a string with PS font names
  75. **  and orientation specification.
  76. */
  77.  
  78. void PSPrintHdr(char *fileName, time_t fileDate, int pages, char *fontNames,
  79.                 Orientation orient)
  80. {
  81.   char dateStr[80],*userStr,*orientStr;
  82.   int paTop,paLft,paHgt,paWdt,iaHgt,iaWdt;
  83.  
  84.   strftime(dateStr,80,"%H:%M Uhr %A, %d. %B %Y",localtime(&fileDate)); /*or %c*/
  85.  
  86.   if(!(userStr = getenv("USER")))
  87.     userStr = "Nobody";
  88.  
  89.   if(orient == ePortrait) {
  90.     orientStr = "Portrait";
  91.     paTop = -31;
  92.     paLft = -30;
  93.     paHgt = 761;
  94.     paWdt = 582;
  95.     iaHgt = 730;
  96.     iaWdt = 552;
  97.   }
  98.   else {
  99.     orientStr = "Landscape";
  100.     paTop = -28;
  101.     paLft = -30;
  102.     paHgt = 566;
  103.     paWdt = 811;
  104.     iaHgt = 538;
  105.     iaWdt = 781;
  106.   }
  107.  
  108.   printf("%%!PS-Adobe-3.0\n"
  109.     "%%%%Title: (%s)\n"
  110.     "%%%%Creator: (pspager: himself)\n"
  111.     "%%%%CreationDate: (%s)\n"
  112.     "%%%%For: (%s)\n"
  113.     "%%%%Pages: %d\n"
  114.     "%%%%DocumentFonts: %s\n"
  115.     "%%%%DocumentNeededFonts: %s\n"
  116.     "%%%%DocumentSuppliedFonts:\n"
  117.     "%%%%DocumentData: Clean7Bit\n"
  118.     "%%%%PageOrder: Ascend\n"
  119.     "%%%%Orientation: %s\n"
  120.     "%%ADO_PaperArea: %d %d %d %d\n"
  121.     "%%ADO_ImageableArea: 0 0 %d %d\n"
  122.     "%%EndComments\n"
  123.     "/md 138 dict def md begin\n"
  124.     "/currentpacking where {pop /sc_oldpacking currentpacking def true setpacking}if\n",
  125.     fileName,dateStr,userStr,pages,fontNames,fontNames,orientStr,paTop,paLft,paHgt,
  126.     paWdt,iaHgt,iaWdt);
  127. }
  128.  
  129.  
  130. /*  PSPrintEnd
  131. **  ----------
  132. **  prints PostScript commands which terminate a document.
  133. */
  134.  
  135. void PSPrintEnd(void)
  136. {
  137.   printf("%%Trailer\nend\t\t%% md\n%%%%EOF\n");
  138. }
  139.  
  140.  
  141. /*  PSInclFile
  142. **  ----------
  143. **  appends the contents of the specified file to stdout. The prefix PSPLIB_DIR is
  144. **  prepended to the file name. #include directives within the included file are
  145. **  recursively substituted (<> means PSP_LIBDIR, "" means current directory).
  146. **  #ifdef directives are evaluated considering symbol definitions made with
  147. **  PSDefSymbol(). #define directives cause further symbol definitions. Unsupported
  148. **  directives are: #undef, #elif.
  149. */
  150.  
  151. void PSInclFile(char *fileName)
  152. {
  153.   FILE *fp;
  154.   char lnBuf[121],*lnPtr,*attr,ch;
  155.   enum { eTokInclude, eTokDefine, eTokIfdef, eTokElse, eTokEndif, eTokIllegal } tok;
  156.   static const char * const tokStrs[] = {
  157.     "include", "define", "ifdef", "else", "endif", "illegal"
  158.   };
  159.   struct {
  160.     enum { ePathIfdef, ePathElse } kind;
  161.     bool taken;
  162.     int  ignCnt;
  163.   } stk[IFSTK_SIZE];
  164.   int idx = -1;
  165.   bool taken,prtIt = TRUE;
  166.  
  167.   if(!(fp = fopen(fileName,"r"))) {
  168.     printf("%%%%pspager error: could not include \"%s\"\n",fileName);
  169.     return;
  170.   }
  171.   while(fgets(lnBuf,121,fp))
  172.     if(lnBuf[0] == '#') {
  173.       for(lnPtr=lnBuf+1; isalpha(*lnPtr); lnPtr++);
  174.       *lnPtr = '\0', lnPtr++;
  175.       for(tok=eTokInclude; tok<eTokIllegal; tok++)
  176.         if(strcmp(lnBuf+1,tokStrs[tok]) == 0)
  177.           break;
  178.       while(*lnPtr==' ')
  179.         lnPtr++; 
  180.       if(tok==eTokDefine || tok==eTokIfdef) {
  181.         attr = lnPtr;
  182.         while(isalnum(*lnPtr) || *lnPtr=='_')
  183.           lnPtr++;
  184.         *lnPtr = '\0';
  185.       }
  186.       switch(tok) {
  187.         case eTokInclude:
  188.           if(prtIt) {
  189.             ch = *lnPtr=='<' ? '>' : '"', lnPtr++;
  190.             attr = lnPtr;
  191.             if(!(lnPtr = strchr(lnPtr,ch))) {
  192.               puts("%%pspager error: invalid syntax");
  193.               continue;
  194.             }
  195.             *lnPtr = '\0';
  196.             if(ch == '>') 
  197.               attr = TackOn(PSP_LIBDIR,attr);
  198.             PSInclFile(attr);
  199.           }
  200.           break;
  201.         case eTokDefine:
  202.           if(prtIt)
  203.             PSDefSymbol(attr);
  204.           break;
  205.         case eTokIfdef:
  206.           if(idx < 0 || stk[idx].taken) {
  207.             idx++;
  208.             if(idx == IFSTK_SIZE)
  209.               FatalExit("#ifdef stack overflow");
  210.             stk[idx].kind = ePathIfdef;
  211.             stk[idx].taken = PSSymDefined(attr);
  212.             stk[idx].ignCnt = 0;
  213.             prtIt = stk[idx].taken;
  214.           }
  215.           else if(!stk[idx].taken)
  216.             stk[idx].ignCnt++;
  217.           break;
  218.         case eTokElse:
  219.           if(idx < 0) {
  220.             puts("%%pspager error: else without ifdef");
  221.             continue;
  222.           }
  223.           if(stk[idx].ignCnt > 0)
  224.             continue;
  225.           if(stk[idx].kind == ePathElse) {
  226.             puts("%%pspager error: unbalanced else");
  227.             continue;
  228.           }
  229.           stk[idx].kind = ePathElse;
  230.           taken = stk[idx].taken;
  231.           prtIt = stk[idx].taken = !taken;
  232.           break;
  233.         case eTokEndif:
  234.           if(idx < 0) {
  235.             puts("%%pspager error: unbalanced endif");
  236.             continue;
  237.           }
  238.           if(stk[idx].ignCnt > 0)
  239.             stk[idx].ignCnt--;
  240.           else {
  241.             idx--;
  242.             if(idx < 0 || stk[idx].taken)
  243.               prtIt = TRUE;
  244.           }
  245.           break;
  246.         default:
  247.           puts("%%pspager error: unrecognized token");
  248.       }
  249.     }
  250.     else
  251.       if(prtIt)
  252.         printf("%s",lnBuf); /*puts() appends a NL*/
  253.   fclose(fp);
  254. }
  255.  
  256.  
  257. /*  PSDefSymbol
  258. **  -----------
  259. **  defines a preprocessor symbol for evaluation by PSInclFile().
  260. **  Multiple definitions are ignored.
  261. */
  262.  
  263. void PSDefSymbol(char *symName)
  264. {
  265.   char *cp;
  266.   int h = 0,d = 1;
  267.  
  268.   if(!symBuf) {
  269.     symBuf = NEW(char,SYMBUF_SIZE);
  270.     symPtr = symBuf;
  271.     symEnd = symBuf+SYMBUF_SIZE;
  272.     symTab = NEW(char *,SYMTAB_SIZE);
  273.     memset(symTab,0,SYMTAB_SIZE*sizeof(char *));
  274.   }
  275.  
  276.   for(cp=symName; *cp!='\0'; cp++)
  277.     h = (256*h + *cp) % SYMTAB_SIZE;
  278.   FOREVER
  279.     if(symTab[h])
  280.       if(strcmp(symTab[h],symName) == 0)
  281.         return; /* already defined */
  282.       else {
  283.         h += d; d += 2; /* collision */
  284.         if(h >= SYMTAB_SIZE)
  285.           h -= SYMTAB_SIZE;
  286.         if(d == SYMTAB_SIZE)
  287.           FatalExit("symbol table overflow");
  288.       }
  289.     else
  290.       break; /* empty slot found */
  291.  
  292.   if(symPtr+strlen(symName) >= symEnd)
  293.     FatalExit("symbol buffer overflow");
  294.   symTab[h] = symPtr;
  295.   strcpy(symPtr,symName);
  296.   symPtr += strlen(symName)+1;
  297. }
  298.  
  299.  
  300. /*  PSUndefAll
  301. **  ----------
  302. **  frees all buffers allocated by PSDefSymbol()
  303. */
  304.  
  305. void PSUndefAll(void)
  306. {
  307.   DELETE(symBuf);
  308.   DELETE(symTab);
  309. }
  310.  
  311.  
  312. /*  PSReadFile
  313. **  ----------
  314. **  reads the contents of the specified file into internal buffers and returns the
  315. **  resulting number of pages.
  316. */
  317.  
  318. int PSReadFile(FILE *inFile)
  319. {
  320.   char lnBuf[121],*lnPtr,*wrEnd,*fndPtr;
  321.   int lnCnt = 0,pgCnt = 1;
  322.  
  323.   if(!(inBuf = NEW(char,INBUF_SIZE)))
  324.     FatalExit("no memory for input buffer");
  325.   wrEnd = inBuf+INBUF_SIZE;
  326.   wrPtr = rdPtr = inBuf;
  327.  
  328.   while(fgets(lnBuf,121,inFile)) {
  329.     if(lnBuf[0] == '\f') {
  330.       pgCnt++, lnCnt=0; /* form feed -> new page */
  331.       continue;
  332.     }
  333.     lnPtr = lnBuf;
  334.     while((fndPtr = strpbrk(lnPtr,"()\\\n"))) {
  335.       CpyStr(lnPtr,fndPtr);
  336.       if(*fndPtr == '\n') {
  337.         CpyChar('\0');
  338.         break;
  339.       }
  340.       CpyChar('\\');
  341.       CpyChar(*fndPtr);
  342.       lnPtr = fndPtr+1;
  343.     }
  344.     lnCnt++;
  345.     if(lnCnt == PAGE_LIMIT)
  346.       pgCnt++, lnCnt=0;
  347.   }
  348.   return pgCnt;
  349. }
  350.  
  351.  
  352. /*  PSFreeFile
  353. **  ----------
  354. **  frees the internal buffers allocated by PSReadFile().
  355. */
  356.  
  357. void PSFreeFile(void)
  358. {
  359.   DELETE(inBuf);
  360. }
  361.  
  362.  
  363. /*  PSNextLine
  364. **  ----------
  365. **  returns a pointer to the next line of the file read by PSReadFile(). The '\n' has
  366. **  been stripped and to all (, ) and \ characters a \ has been preprended. If there
  367. **  are no more lines, NULL is returned.
  368. */
  369.  
  370. char *PSNextLine(void)
  371. {
  372.   char *p;
  373.  
  374.   if(rdPtr < wrPtr) {
  375.     p = rdPtr;
  376.     rdPtr += strlen(p)+1;
  377.     return p;
  378.   }
  379.   else
  380.     return NULL;
  381. }
  382.  
  383.  
  384. /*  TackOn
  385. **  ------
  386. **  concatenates a path name and a file name to a full path name. The returned string
  387. **  is owned by the caller (so it has to be freed by him/her).
  388. */
  389.  
  390. char *TackOn(const char *pn, const char *fn)
  391. {
  392.   int n = strlen(pn);
  393.   char *fpn;
  394.  
  395.   if (n == 0) {
  396.     fpn = NEW(char, strlen(fn)+1);
  397.     strcpy(fpn, fn);
  398.   }
  399.   else if(pn[n-1] == '/' || pn[n-1] == ':') {
  400.     fpn = NEW(char, n+strlen(fn)+1);
  401.     sprintf(fpn,"%s%s",pn,fn);
  402.   }
  403.   else {
  404.     fpn = NEW(char, n+strlen(fn)+2);
  405.     sprintf(fpn,"%s/%s",pn,fn);
  406.   }
  407.   return fpn;
  408. }
  409.